package me.fung.wubi.base.define.table

import me.fung.wubi.base.define.action.ProcessAction
import me.fung.wubi.base.define.action.runInBackground
import me.fung.wubi.base.define.value.Code
import me.fung.wubi.base.define.value.Word
import me.fung.wubi.base.define.value.toCode
import me.fung.wubi.base.define.value.toWord
import me.fung.wubi.base.io.autoReadLines
import java.io.File

fun Word.buildCode(lexicon: Lexicon): Code {
    val len = value.length
    val resultValue = value.toCharArray().map { char ->
        lexicon.codeOfWord(Word(char.toString()))//每个字的编码
    }.mapIndexed { index, code ->
        val codeValue = code.value
        when (len) {
            1 -> codeValue
            2 -> {
                codeValue.substring(0..1)//2字词条，取每个字的前2个编码
            }

            3 -> {
                when (index) {
                    0 -> codeValue.substring(0..0) //3字词条取第1字的第1个编码
                    1 -> codeValue.substring(0..0) //3字词条取第2字的第1个编码
                    else -> codeValue.substring(0..1) //3字词条取第3字的前2个编码
                }
            }

            else -> {
                when (index) {
                    0, 1, 2, len - 1 -> codeValue.substring(0..0) //四字词条取前3个字和最后一个字的第1个编码
                    else -> ""
                }
            }
        }

    }.joinToString("")
    return resultValue.toCode()
}

/**
 * 从词语文本中创建
 * @param wordFile 单字或词组，无编码的文件。
 */
fun CodeTable(lexicon: Lexicon, wordFile: File, action: ProcessAction? = null): CodeTable {
    val result = CodeTable()
    wordFile.autoReadLines().forEach { line ->
        line.split(' ', '\t').forEach FE@{
            if (it.startsWith("#")) return@FE
            if (it.isBlank()) return@FE
            val word = it.toWord()
            val code = word.buildCode(lexicon)
            action.runInBackground(code, word)
            result.add(code, word)
        }
    }
    return result
}

fun CodeTable(lexicon: Lexicon, action: ProcessAction? = null): CodeTable = CodeTable().apply {
    addLexicon(lexicon, action)
}

fun CodeTable.addLexicon(lexicon: Lexicon, action: ProcessAction? = null) {
    lexicon.forEach { (word, code) ->
        action.runInBackground(code, word)
        add(code, word)
    }
}